#include "NetUtils.h"
#include "spdlog/spdlog.h"
#include <functional>

namespace LiteNetLib::NetUtils
{

    size_t hash_bytes(const void *data, size_t length)
    {
        const unsigned char *bytes = static_cast<const unsigned char *>(data);
        size_t hash = 5381;
        for (size_t i = 0; i < length; ++i)
        {
            hash = ((hash << 5) + hash) ^ bytes[i];
        }
        return hash;
    }

    size_t SockHashCode(net_endpoint *sa)
    {
        if (sa->sa_family == AF_INET)
        {
            const struct sockaddr_in *sa_in = reinterpret_cast<const struct sockaddr_in *>(sa);
            // 哈希计算IPv4地址和端口
            size_t addr_hash = hash_bytes(&(sa_in->sin_addr), sizeof(sa_in->sin_addr));
            size_t port_hash = hash_bytes(&(sa_in->sin_port), sizeof(sa_in->sin_port));
            return addr_hash ^ port_hash; // 使用异或操作结合地址和端口的哈希值
        }
        else if (sa->sa_family == AF_INET6)
        {
            const struct sockaddr_in6 *sa_in6 = reinterpret_cast<const struct sockaddr_in6 *>(sa);
            // 哈希计算IPv6地址和端口
            size_t addr_hash = hash_bytes(&(sa_in6->sin6_addr), sizeof(sa_in6->sin6_addr));
            size_t port_hash = hash_bytes(&(sa_in6->sin6_port), sizeof(sa_in6->sin6_port));
            return addr_hash ^ port_hash; // 使用异或操作结合地址和端口的哈希值
        }
        // 处理其他地址族或返回默认值
        return 0;
    }

    std::string GetAddressStr(net_endpoint *endpoint)
    {
        std::string sockAddress;
        UdpServer::getAddress(endpoint, sockAddress);
        return sockAddress;
    }

    std::string GetSockIP(net_endpoint *endpoint)
    {
        std::string sockIp;
        UdpServer::getIpStr(endpoint, sockIp);
        return sockIp;
    }

    uint64_t ByteToUInt64(const char *buff)
    {
        uint64_t value;
        memcpy(&value, buff, sizeof(value));
        return value;
    }

    int64_t ByteToInt64(const char *buff)
    {
        int64_t value;
        memcpy(&value, buff, sizeof(value));
        return value;
    }

    uint32_t ByteToUInt32(const char *buff)
    {
        uint32_t value;
        memcpy(&value, buff, sizeof(value));
        return value;
    }

    int32_t ByteToInt32(const char *buff)
    {
        int32_t value;
        memcpy(&value, buff, sizeof(value));
        return value;
    }

    uint16_t ByteToUInt16(const char *buff)
    {
        uint16_t value;
        memcpy(&value, buff, sizeof(value));
        return value;
    }

    int16_t ByteToInt16(const char *buff)
    {
        int16_t value;
        memcpy(&value, buff, sizeof(value));
        return value;
    }

    void UInt64ToByte(char *buff, uint64_t value)
    {
        memcpy(buff, &value, sizeof(value));
    }

    void Int64ToByte(char *buff, int64_t value)
    {
        memcpy(buff, &value, sizeof(value));
    }

    void UInt32ToByte(char *buff, uint32_t value)
    {
        memcpy(buff, &value, sizeof(value));
    }

    void Int32ToByte(char *buff, int32_t value)
    {
        memcpy(buff, &value, sizeof(value));
    }

    void UInt16ToByte(char *buff, uint16_t value)
    {
        memcpy(buff, &value, sizeof(value));
    }

    void Int16ToByte(char *buff, int16_t value)
    {
        memcpy(buff, &value, sizeof(value));
    }

    std::string ToHexString(const void *ptr, uint32_t length)
    {
        static char *hexStringCatch = nullptr;
        static uint32_t hexCatchSize = 0;

        if (hexCatchSize < length * 3)
        {
            delete[] hexStringCatch;
            int size = length * 3 + 128;
            hexStringCatch = new char[size];
            hexCatchSize = size;
        }

        for (int index = 0; index < length; index++)
        {
            sprintf(&(hexStringCatch[index * 3]), "%02X ", ((const unsigned char *)ptr)[index]);
        }
        hexStringCatch[length * 3 - 1] = '\0';
        return hexStringCatch;
    }

}
